import celery
import json
import pagure
import rdflib

from .. import activitypub
from .. import model
from .. import settings

from . import broker
from . import broker_url
from . import database_session

log = celery.utils.log.get_task_logger(__name__)
log.setLevel(settings.LOG_LEVEL)

@broker.task
def handle_incoming_activity(person_id, activity):
    """
    A person has received a new Activity in its INBOX. This task is scheduled
    in order to triage the activity and decide how the actor should react to it.
    """
    
    activity = activitypub.Document(activity)
    
    with database_session() as (pagure_db, forgefed_db):
        
        person = pagure_db.query(model.Person) \
                          .filter(model.Person.id == person_id) \
                          .one_or_none()
        
        # If the person doesn't exist, it means it was deleted after it received
        # an Activity but before the Activity was handled.
        if not person:
            log.info('Actor {} doesn\'t exist. Incoming Activity will be ignored.'.format(person.local_uri))
            return
        
        if activity['type'] == 'Accept' \
        and activity.node('object')['type'] == 'Follow' \
        and activity['object']['actor'] == person.local_uri \
        and activity['object']['id'] == activity['actor']:
            """
            We have received a response to our Follow request.
            """
            
            log.debug('Actor {} has accepted the Follow request by {}'.format(activity['actor'], person.local_uri))
        
        if activity['type'] == 'Accept' \
        and activity.node('object')['type'] == 'Offer' \
        and activity['object']['actor'] == person.local_uri \
        and activity['object']['object']['type'] == 'Ticket' \
        and 'result' in activity \
        and activity['actor'] == activity['object']['to']:
            """
            We have received a response to our Offer(Ticket) request.
            """
            
            log.debug('The remote actor has accepted the Ticket offer.')
            
            ticket = activity.node('object').node('object')
            
            # Remember that our local Ticket is a view of a remote Ticket
            forgefed_db.add(database.SameAs(
                local_uri = ticket['id'],
                remote_uri = activity['result']))
            
            log.debug('The ticket {} was accepted. A new ticket was created at {}'.format(ticket['id'], activity['result']))
        
        if activity['type'] == 'Create' \
        and activity.node('object')['type'] == 'Note' \
        and 'context' in activity['object']:
            """
            Somebody has created a new Note for a Ticket or a MergeRequest.
            """
            
            log.debug('Somebody has Created a new Note.')
            
            model.test_or_set_remote_comment(pagure_db, forgefed_db, activity['object']['id'])
        
        if activity['type'] == 'Follow' \
        and activity['object'] == person.local_uri:
            """
            Somebody has Followed this actor..
            """
            
            # Check if the remote actor is already following the local actor
            if forgefed_db.query(
                   forgefed_db.query(database.Collection) \
                              .filter(database.Collection.uri == person.followers_uri) \
                              .filter(database.Collection.item == activity['actor']) \
                              .exists()
                ).scalar():
                
                log.info('Actor {} is already following {}. Will ignore Follow request.'.format(person.local_uri, activity['actor']))
                return
            
            # Add the remote object to our followers collection
            forgefed_db.add(database.Collection(uri = person.followers_uri, item = activity['actor']))
            
            # Commit before accepting the Activity because we want the new
            # follower in the Followers collection before sending out the
            # Accept Activity.
            forgefed_db.commit()
            
            # Automatically accept Follow requests.
            person.accept(activity)
        
        if activity['type'] == 'Resolve' \
        and activity.node('object')['type'] == 'Ticket':
            """
            We've been notified that somebody has resolved a remote Ticket.
            """
            
            # Check if we have any local object representing the remote Ticket,
            # in which case we will update our local copy.
            ticket = forgefed_db.query(database.SameAs) \
                       .filter(database.SameAs.remote_uri == activity['object']['id']) \
                       .one_or_none()
            
            if not ticket:
                log.debug('The Ticket {} is not cached locally.'.format(activity['object']['id']))
                return
            
            log.debug('Ticket resolved: {}'.format(activity['object']['id']))
            
            #-----------
            
            # Edit the pagure Issue object
            pagure.lib.query.edit_issue(
                session=pagure_db,
                issue=ticket,
                user=actor.username,
                status='Closed')
        











